<template>
  <div id="animation"></div>
</template>

<script setup>
import { onMounted } from 'vue'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

/**
 * 几何顶点位置数据和点模型
 * 步骤：
 * 1. 创建一个 BufferGeometry 实例，用于存储顶点数据
 * 2. 创建一个 Float32Array 实例，用来表示x、y、z坐标数据
 * 3. 创建一个 BufferAttribute 实例，将顶点数据存储到 BufferGeometry 实例中
 * 4. 通过setAttribute设计几何体的顶点位置
 *
 * 点模型
 * 1. 创建一个 PointsMaterial 实例，设置点的颜色和大小
 * 2. 创建一个 Points 实例，传入 BufferGeometry 实例和 PointsMaterial 实例
 */

let camera, scene, renderer
let points
function init() {
  camera = new THREE.PerspectiveCamera(27, window.innerWidth / window.innerHeight, 5, 3500)
  camera.position.z = 2750

  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x050505)
  scene.fog = new THREE.Fog(0x050505, 2000, 3500)

  const particles = 500000

  const geometry = new THREE.BufferGeometry()

  const positions = []
  const colors = []

  const color = new THREE.Color()

  const n = 1000,
    n2 = n / 2 // particles spread in the cube

  for (let i = 0; i < particles; i++) {
    // positions

    const x = Math.random() * n - n2
    const y = Math.random() * n - n2
    const z = Math.random() * n - n2

    positions.push(x, y, z)

    // colors

    const vx = x / n + 0.5
    const vy = y / n + 0.5
    const vz = z / n + 0.5

    color.setRGB(vx, vy, vz, THREE.SRGBColorSpace)

    colors.push(color.r, color.g, color.b)
  }

  geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3))
  geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3))
  geometry.computeBoundingSphere()

  const material = new THREE.PointsMaterial({ size: 15, vertexColors: true })

  points = new THREE.Points(geometry, material)
  scene.add(points)

  renderer = new THREE.WebGLRenderer()
  renderer.setPixelRatio(window.devicePixelRatio)
  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setAnimationLoop(animate)
  window.addEventListener('resize', onWindowResize)
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
}

function animate() {
  const time = Date.now() * 0.001
  points.rotation.x = time * 0.25
  points.rotation.y = time * 0.5
  renderer.render(scene, camera)
}
onMounted(() => {
  init()
  animate()
  document.getElementById('animation').appendChild(renderer.domElement)
  new OrbitControls(camera, renderer.domElement)
})
</script>

<style>
</style>